# =============================================================================
# Note Management Functions
# =============================================================================
function note {
    [CmdletBinding()]
    param(
        [Parameter(Position = 0)]
        [ValidateSet('add', 'open', 'list', 'search', 'delete', 'help')]
        [string]$Command,

        [Parameter(Position = 1, ValueFromRemainingArguments = $true)]
        [string[]]$Arguments
    )

    $noteDir = Join-Path $HOME "note/local"
    $date = Get-Date -Format "yyyy-MM-dd"
    $noteFile = Join-Path $noteDir "$date.md"

    # Ensure note directory exists
    if (-not (Test-Path $noteDir)) {
        try {
            New-Item -ItemType Directory -Path $noteDir -Force | Out-Null
            Write-Verbose "Created note directory: $noteDir"
        }
        catch {
            Write-Error "Error: Failed to create directory $noteDir - $($_.Exception.Message)"
            return
        }
    }

    switch ($Command) {
        'add' {
            if ($Arguments.Count -eq 0) {
                Write-Error "Error: No content provided for note."
                return
            }

            $content = $Arguments -join ' '
            $timestamp = Get-Date -Format "HH:mm:ss"
            $noteContent = "[$timestamp] $content"

            try {
                Add-Content -Path $noteFile -Value $noteContent
                Write-Host "Note added to $noteFile"
            }
            catch {
                Write-Error "Error: Failed to write to $noteFile"
            }
        }

        'open' {
            if (-not (Test-Path $noteFile)) {
                try {
                    New-Item -ItemType File -Path $noteFile -Force | Out-Null
                }
                catch {
                    Write-Error "Error: Failed to create $noteFile"
                    return
                }
            }

            # Use the configured editor (nvim in your case)
            $editor = $env:EDITOR
            if ($editor -match 'nvim|vim') {
                & $editor -c "cd $noteDir" -c "lcd $noteDir" $noteFile
            }
            else {
                Push-Location $noteDir
                & $editor $noteFile
                Pop-Location
            }
        }

        'list' {
            if (Test-Path $noteDir) {
                $files = Get-ChildItem -Path $noteDir -Filter "*.md"
                if ($files.Count -gt 0) {
                    Write-Host "Available notes in ${noteDir}:"
                    $files | Sort-Object LastWriteTime -Descending | ForEach-Object {
                        Write-Host ("{0} - {1} - {2:N2} KB" -f $_.LastWriteTime.ToString("yyyy-MM-dd HH:mm"), $_.Name, ($_.Length/1KB))
                    }
                }
                else {
                    Write-Host "No notes found in $noteDir"
                }
            }
            else {
                Write-Host "No notes found in $noteDir"
            }
        }

        'search' {
            if ($Arguments.Count -eq 0) {
                Write-Error "Error: No search term provided."
                return
            }

            $searchTerm = $Arguments[0]
            Write-Host "Searching for `"$searchTerm`" in notes:"

            $found = $false
            Get-ChildItem -Path $noteDir -Filter "*.md" | ForEach-Object {
                if (Select-String -Path $_.FullName -Pattern $searchTerm -Quiet) {
                    Write-Host $_.Name
                    $found = $true
                }
            }

            if (-not $found) {
                Write-Host "No matches found."
            }
            else {
                Write-Host "Found matches in above files."
            }
        }

        'delete' {
            $targetFile = $noteFile
            if ($Arguments.Count -gt 0 -and $Arguments[0] -match '^\d{4}-\d{2}-\d{2}$') {
                $targetFile = Join-Path $noteDir "$($Arguments[0]).md"
            }

            if (Test-Path $targetFile) {
                $confirm = Read-Host "Are you sure you want to delete $targetFile? (y/n)"
                if ($confirm -match '^[yY]') {
                    try {
                        Remove-Item $targetFile -Force
                        Write-Host "Note deleted: $targetFile"
                    }
                    catch {
                        Write-Error "Error: Failed to delete $targetFile"
                    }
                }
                else {
                    Write-Host "Deletion cancelled."
                }
            }
            else {
                Write-Error "Error: Note file $targetFile does not exist."
            }
        }

        'help' {
            Write-Host @"
Note Management System
=====================
Usage:
  note add <content>   - Add a new note with timestamp
  note open            - Open today's note in editor
  note list            - List all available notes
  note search <term>   - Search notes for specific term
  note delete [date]   - Delete today's note or specified date (YYYY-MM-DD)
  note help            - Show this help message

Examples:
  note add "Meeting with client at 2 PM"
  note search "meeting"
  note delete 2024-01-15
"@
        }

        default {
            Write-Host "Unknown command: $Command" -ForegroundColor Red
            Write-Host "Use 'note help' to see available commands." -ForegroundColor Yellow
        }
    }
}



# =============================================================================
# Utility Functions
# =============================================================================
function ts2date {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [long]$Timestamp
    )

    $timestampStr = $Timestamp.ToString()
    $length = $timestampStr.Length

    try {
        switch ($length) {
            10 {
                # Unix 时间戳（秒）
                $datetime = [DateTimeOffset]::FromUnixTimeSeconds($Timestamp).DateTime
            }
            13 {
                # 毫秒级时间戳
                $datetime = [DateTimeOffset]::FromUnixTimeMilliseconds($Timestamp).DateTime
            }
            default {
                Write-Error "无法识别的时间戳长度，请输入10位（Unix时间戳）或13位（毫秒级时间戳）的时间戳。当前长度: $length"
                return
            }
        }

        Write-Output $datetime
    }
    catch {
        Write-Error "时间戳转换失败: $($_.Exception.Message)"
    }
}



function case {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Number
    )

    # 1. 根目录，按需修改
    $root = 'X:\Cases\2025'

    # 2. 去掉用户可能输入的前导 0（如 007 → 7）
    $Number = $Number.TrimStart('0')
    if ([string]::IsNullOrEmpty($Number)) { $Number = '0' }

    # 3. 构造通配符
    $pattern = "2025-$Number"

    # 4. 查找
    $matches = Get-ChildItem -Path $root -Directory -Filter $pattern

    switch ($matches.Count) {
        0 { Write-Warning "未找到目录：$root\$pattern" }
        1 { Set-Location $matches[0].FullName }
        default {
            Write-Host "找到多个匹配目录，请选择："
            $matches | Select-Object FullName | Out-Host
        }
    }
}


function doc {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [ValidateNotNullOrEmpty()]
        [string]$Number
    )

    # 1. 修改根目录为 Docs 下的路径
    $root = 'X:\Docs\SH\2025'

    # 2. 去掉用户可能输入的前导 0（如 095 → 95）
    $Number = $Number.TrimStart('0')
    if ([string]::IsNullOrEmpty($Number)) { $Number = '0' }

    # 3. 构造匹配模式 (例如输入 95 -> 匹配 2025-95)
    $pattern = "2025-$Number"

    # 4. 查找
    # 注意：如果目录不存在，Get-ChildItem 会抛错，建议加 -ErrorAction SilentlyContinue
    # 或者让 switch 的 0 分支处理找不到的情况 (当前逻辑依赖 $matches.Count)
    $matches = Get-ChildItem -Path $root -Directory -Filter $pattern -ErrorAction SilentlyContinue

    if ($null -eq $matches) {
        Write-Warning "未找到目录：$root\$pattern"
        return
    }

    switch ($matches.Count) {
        0 { Write-Warning "未找到目录：$root\$pattern" }
        1 { Set-Location $matches[0].FullName }
        default {
            Write-Host "找到多个匹配目录，请选择："
            $matches | Select-Object FullName | Out-Host
        }
    }
}



## enable UTF-8

#  $OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = New-Object System.Text.UTF8Encoding


function hashcal {
    [CmdletBinding()]
    param(
        # 把 Mandatory 设为 $true
        [Parameter(Mandatory = $true, Position = 0, ValueFromRemainingArguments = $true)]
        [string[]] $Path
    )

    process {
        foreach ($p in $Path) {
            # 支持通配符展开
            $files = Get-ChildItem -Path $p -File -ErrorAction SilentlyContinue
            if (-not $files) { $files = Get-Item -LiteralPath $p -ErrorAction SilentlyContinue }

            foreach ($file in $files) {
                $sha = (Get-FileHash -LiteralPath $file.FullName -Algorithm SHA256).Hash.ToUpper()
                Write-Output ("文件: {0}" -f $file.FullName)
                Write-Output ("大小: {0} 字节" -f $file.Length)
                Write-Output ("SHA-256: {0}" -f $sha)
                Write-Output ""
            }
        }
    }
}

function caseinit {
    # 要创建的文件夹列表
    $dirs = @('000-检材信息', '100-哈希校验')

    foreach ($d in $dirs) {
        # 如果目录不存在就建
        if (-not (Test-Path $d)) {
            $null = New-Item -ItemType Directory -Name $d
            Write-Host "已创建目录：$d"
        } else {
            Write-Host "目录已存在，跳过：$d"
        }
    }
}





function Symlink-File {
    $DestPath = $args[0]
    $SourcePath = $args[1]
    if (Test-Path $DestPath) {
        Write-Warning "$DestPath is already symlinked"
    } else {
        if ((Get-Item $SourcePath) -is [System.IO.DirectoryInfo]) {
            cmd /c mklink /D "$DestPath" "$SourcePath"
        } else {
            cmd /c mklink "$DestPath" "$SourcePath"
        }
        echo "$DestPath has been symlinked"
    }
}

function Unsymlink-File {
    $DestPath = $args[0]
    $SourcePath = $args[1]
    if (Test-Path $DestPath) {
        if ((Get-Item $SourcePath) -is [System.IO.DirectoryInfo]) {
            cmd /c rmdir "$DestPath"
        } else {
            cmd /c del "$DestPath"
        }
        echo "$DestPath has been unsymlinked"
    } else {
        Write-Warning "$DestPath doesn't exist"
    }
}

function Deploy-Manifest {
    $ManifestFile = $args[0]

    echo "Deploying $ManifestFile..."

    $Manifest = Import-Csv -Header ("file", "operation") -Delimiter ("|") -Path ".\$ManifestFile"
    $EmacsHome = $env:HOME
    foreach ($ManifestRow in $Manifest) {
        $DeployFile = $ManifestRow.file
        $DeployOp = $ManifestRow.operation
        $SourcePath = "$PSScriptRoot\$DeployFile"
        $DestPath = "$EmacsHome\$DeployFile"
        switch($DeployOp) {
            "symlink" {
                Symlink-File $DestPath $SourcePath
            }

            "copy" {
                Write-Warning "The 'copy' operation is not implemented yet. Skipping..."
            }

            default {
                Write-Warning "Unknown operation $operation. Skipping..."
            }
        }
    }
}

function Undeploy-Manifest {
    $ManifestFile = $args[0]

    echo "Undeploying $ManifestFile..."

    $Manifest = Import-Csv -Header ("file", "operation") -Delimiter ("|") -Path ".\$ManifestFile"
    $EmacsHome = $env:HOME
    foreach ($ManifestRow in $Manifest) {
        $DeployFile = $ManifestRow.file
        $DeployOp = $ManifestRow.operation
        $SourcePath = "$PSScriptRoot\$DeployFile"
        $DestPath = "$EmacsHome\$DeployFile"
        switch($DeployOp) {
            "symlink" {
                Unsymlink-File $DestPath $SourcePath
            }

            "copy" {
                Write-Warning "The 'copy' operation is not implemented yet. Skipping..."
            }

            default {
                Write-Warning "Unknown operation $operation. Skipping..."
            }
        }
    }
}
